package app;

import dataStructure.StackUtil;
import org.junit.Test;

/**
 * @Author xuxin
 * @Date 2021/8/9 22:04
 * 计算器，输出一个表达式的结果 比如输入1+2*3+4，输出11
 **/
public class Calculator {
    private StackUtil<Integer> numStack = new StackUtil<Integer>();
    private StackUtil<Character> operatorStack = new StackUtil<Character>();

    /**
     * 计算表达式的结果
     *
     * @return 结果
     */
    public static Integer calculation(String expression) {
        //用来标记操作符栈栈底的优先级，flag=-1说明是空的
        int flag = -1;
        if (!checkExpression(expression)) {
            throw new RuntimeException("表达式错误");
        }
        Calculator calculator = new Calculator();
        //暂时算10以内的
        for (int i = 0; i < expression.length(); i++) {
            if (Character.isDigit(expression.charAt(i))) {
                calculator.numStack.push(expression.charAt(i) - '0');
            } else {
                if (flag == -1) {
                    calculator.operatorStack.push(expression.charAt(i));
                    flag = priority(expression.charAt(i));
                } else if (priority(expression.charAt(i)) <= flag) {
                    Integer num1 = (Integer) calculator.numStack.pop();
                    Integer num2 = (Integer) calculator.numStack.pop();
                    char operator = (Character) calculator.operatorStack.pop();
                    calculator.numStack.push(partCalculation(num1, num2, operator));
                    calculator.operatorStack.push(expression.charAt(i));
                    flag = priority(expression.charAt(i));
                } else {
                    calculator.operatorStack.push(expression.charAt(i));
                    flag = priority(expression.charAt(i));
                }
            }
        }
        while (calculator.numStack.size() >= 2) {
            Integer num1 = (Integer) calculator.numStack.pop();
            Integer num2 = (Integer) calculator.numStack.pop();
            char operator = (Character) calculator.operatorStack.pop();
            calculator.numStack.push(partCalculation(num1, num2, operator));
        }
        return (Integer) calculator.numStack.pop();
    }

    /**
     * 判断表达式是否合法
     */
    public static boolean checkExpression(String expression) {
        for (int i = 0; i < expression.length(); i++) {
            if ((expression.charAt(i) != '0'
                    && expression.charAt(i) != '1'
                    && expression.charAt(i) != '2'
                    && expression.charAt(i) != '3'
                    && expression.charAt(i) != '4'
                    && expression.charAt(i) != '5'
                    && expression.charAt(i) != '6'
                    && expression.charAt(i) != '7'
                    && expression.charAt(i) != '8'
                    && expression.charAt(i) != '9'
                    && expression.charAt(i) != '*'
                    && expression.charAt(i) != '/'
                    && expression.charAt(i) != '+'
                    && expression.charAt(i) != '_'
            ) && (expression.charAt(0) == '*'
                    || expression.charAt(0) == '/'
                    || expression.charAt(0) == '+'
                    || expression.charAt(0) == '_'
                    || expression.charAt(expression.length()) == '/'
                    || expression.charAt(expression.length()) == '+'
                    || expression.charAt(expression.length()) == '_'
                    || expression.charAt(expression.length()) == '*')) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断符号优先级,返回的数字越大，优先级越高
     */
    public static int priority(char c) {
        if (c == '*' || c == '/') {
            return 1;
        } else if (c == '+' || c == '-') {
            return 0;
        }
        throw new RuntimeException("表达式错误");
    }

    /**
     * 计算短式
     */
    public static int partCalculation(int a, int b, char c) {
        if (c == '+') {
            return b + a;
        }
        if (c == '-') {
            return b - a;
        }
        if (c == '*') {
            return a * b;
        }
        if (c == '/') {
            return b / a;
        }
        return 0;
    }

    @Test
    public void test() {
        System.out.println(Calculator.calculation("5+2*4*5"));
    }

}
